/*
 * DetectorConstruction.cc
 *
 *  Created on: 12.02.2011
 *      Author: ed
 */

#include "DetectorConstruction.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
#include "G4Element.hh"
#include "G4LogicalBorderSurface.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4RotationMatrix.hh"
#include "G4ThreeVector.hh"
#include "G4PVPlacement.hh"
#include "G4OpBoundaryProcess.hh"
#include "G4Sphere.hh"
#include "G4GeometryManager.hh"
#include "G4SDManager.hh"
#include "TrackerSD.hh"
#include "PrimariesGenerator.hh"
#include "globals.hh"
G4double DetectorConstruction::lAbs = 0.5*m;
G4double DetectorConstruction::lSc = 10*cm;
G4double DetectorConstruction::sphereRadius = 1*m;
DetectorConstruction::DetectorConstruction(G4double R=1*m)
{
	sphereRadius = R;
	boxSide = sphereRadius * 1.1;
	G4String detectorName = "Aerogel Sphere";
	trackerSD = new TrackerSD(detectorName);
}
DetectorConstruction::DetectorConstruction(G4double R,G4double LAbs,G4double LSc)
{
	sphereRadius = R;
	boxSide = sphereRadius * 1.1;
	G4String detectorName = "Aerogel Sphere";
	trackerSD = new TrackerSD(detectorName);

	lAbs = LAbs;
	lSc=LSc;
}
DetectorConstruction::~DetectorConstruction()
{

}
G4VPhysicalVolume* DetectorConstruction::Construct()
{
	G4Element* N = new G4Element("Nitrogen", "N", 7 , 14.01*g/mole);
	G4Element* O = new G4Element("Oxygen"  , "O", 8 , 16.00*g/mole);

	G4Material* Air = new G4Material("Air", 1.29*mg/cm3, 2);
	Air->AddElement(N, 70.*perCent);
	Air->AddElement(O, 30.*perCent);


	G4Material* Aerogel = new G4Material("Aerogel", 0.1*g/cm3,0);

	G4MaterialPropertiesTable* airMPT = new G4MaterialPropertiesTable();
	G4MaterialPropertiesTable* aerogelMPT = new G4MaterialPropertiesTable();
	const G4int nEntries = 5;
	G4double PhotonEnergy[nEntries];
	for(int i=0;i<nEntries;i++)
	{
		PhotonEnergy[i] = PrimariesGenerator::GetPhotonEnergy()
			+(double)(i+2-nEntries)*PrimariesGenerator::GetPhotonEnergy()/(double)nEntries;

	}


	//
	// Aerogel
	//
	G4double AerogelRefractiveIndex[nEntries];
	for(int i=0;i<nEntries;i++)
	{
		AerogelRefractiveIndex[i]=1.3;
	}

	  G4double AerogelAbsorption[nEntries];
	  for(int i=0;i<nEntries;i++)
	  {
		  AerogelAbsorption[i]=lAbs;
	  }

	  G4double AirRefractiveIndex[nEntries];
	  for(int i=0;i<nEntries;i++)
	  {
	  		  AirRefractiveIndex[i]=1.0;
	  }
	  G4double AerogelReyleighScaterring[nEntries];
	  for(int i=0;i<nEntries;i++)
	  {
		  AerogelReyleighScaterring[i]=lSc;
	  }


	  aerogelMPT->AddProperty("RAYLEIGH",PhotonEnergy,AerogelReyleighScaterring,nEntries);
	  aerogelMPT->AddProperty("ABSLENGTH",PhotonEnergy,AerogelAbsorption,nEntries);
	  aerogelMPT->AddProperty("RINDEX",PhotonEnergy,AerogelRefractiveIndex,nEntries);

	  airMPT->AddProperty("RINDEX",PhotonEnergy,AirRefractiveIndex,nEntries);

	  Aerogel->SetMaterialPropertiesTable(aerogelMPT);
	  Air->SetMaterialPropertiesTable(airMPT);

	  G4Box* bigAirBox = new G4Box("BigAirBox",boxSide,boxSide,boxSide);
	  G4LogicalVolume* bigAirBoxLogical = new G4LogicalVolume(bigAirBox,Air,"AirLogicalBox");


	  airBoxPhys
	      = new G4PVPlacement(0,G4ThreeVector(),bigAirBoxLogical,"World",0,false,0);


	  G4Sphere* aerogelSphere = new G4Sphere("AerogelSphere",0.0,sphereRadius,0.0,2*pi,0.0,pi);
	  G4LogicalVolume* aerogelSphereLogical = new G4LogicalVolume(aerogelSphere,Aerogel,"AerogelSphere");

	  aerogelSpherePhys = new G4PVPlacement(0,G4ThreeVector(),aerogelSphereLogical,"AerogelSpherePhys",
								  bigAirBoxLogical,false,0);



	  G4SDManager *sdMan = G4SDManager::GetSDMpointer();
	  if(sdMan)
	  {

		  sdMan->AddNewDetector(trackerSD);
		  aerogelSphereLogical->SetSensitiveDetector(trackerSD);
	  }
	  G4OpticalSurface* aerogelSurface = new G4OpticalSurface("WaterSurface");
	  aerogelSurface->SetType(dielectric_dielectric);
	  aerogelSurface->SetFinish(polished);
	  aerogelSurface->SetModel(unified);
	  //The UNIFIED model assumes that the probability of micro-facet
	  //normals populates the annulus of solid angle sin(a)da will be
	  //proportional to a gaussian of SigmaAlpha

	  aerogelSurface->SetSigmaAlpha(0.1);

	  //G4LogicalBorderSurface* WaterSurface =
	                                 new G4LogicalBorderSurface("WaterSurface",
	                                 aerogelSpherePhys,airBoxPhys,aerogelSurface);




	  return airBoxPhys;
}
void DetectorConstruction::SetMediumProperties(G4double LAbs,G4double LSc)
{
	G4GeometryManager *geometryManager = G4GeometryManager::GetInstance();
	if(LAbs==lAbs&&LSc==lSc)
		return;
	if(geometryManager==0)
	{
		G4cout<<"Geometry manager is not instantiated yet"<<G4endl;
		return;
	}
	geometryManager->OpenGeometry(aerogelSpherePhys);
	G4MaterialPropertiesTable *t = aerogelSpherePhys->GetLogicalVolume()->GetMaterial()->GetMaterialPropertiesTable();
	G4double pe = PrimariesGenerator::GetPhotonEnergy();
	t->RemoveEntry("ABSLENGTH",pe);
	t->RemoveEntry("RAYLEIGH",pe);
	lAbs = LAbs;
	lSc = LSc;
	t->AddEntry("ABSLENGTH",pe,lAbs);
	t->AddEntry("RAYLEIGH",pe,lSc);
	geometryManager->CloseGeometry(aerogelSpherePhys);

}
void DetectorConstruction::SetRadius(G4double radius)
{
	G4GeometryManager *geometryManager = G4GeometryManager::GetInstance();
	if(geometryManager==0)
	{
		G4cout<<"Geometry manager is not instantiated yet"<<G4endl;
		return;
	}

	geometryManager->OpenGeometry(airBoxPhys);
	geometryManager->OpenGeometry(aerogelSpherePhys);
	G4Box* airBox = dynamic_cast<G4Box*>(airBoxPhys->GetLogicalVolume()->GetSolid());
	G4Sphere* aerogelSphere = dynamic_cast<G4Sphere*>(aerogelSpherePhys->GetLogicalVolume()->GetSolid());
	if(airBox!=0&&aerogelSphere!=0)
	{

		airBox->SetXHalfLength(radius*1.1);
		airBox->SetYHalfLength(radius*1.1);
		airBox->SetZHalfLength(radius*1.1);
		aerogelSphere->SetOuterRadius(radius);
		trackerSD->setDetectorRadius(radius);
		sphereRadius = radius;
	}
	else
	{
		G4cerr<<"error during radius changing"<<G4endl;
	}
	geometryManager->CloseGeometry(aerogelSpherePhys);
	geometryManager->CloseGeometry(airBoxPhys);
	return;
}
